home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / dfix12.zip / DFIX.C < prev    next >
Text File  |  1991-05-08  |  10KB  |  318 lines

  1. /*
  2. **            DFIX Copyright (C) 1985, 1986  Howard Rumsey Jr.
  3. **
  4. **    DFIX disk fix utility. Reads the whole DOS partion on a disk (floppy,
  5. **    hard disk, ramdisk) and, if directed, marks bad clusters in the FAT(s).
  6. **
  7. **    Usage:
  8. **            dfix [d:]
  9. **
  10. **        d: is an optional device specifier. If not specified DFIX will
  11. **            use the default device.
  12. **
  13. **    If DFIX finds a bad cluster already allocated to a file this will
  14. **    be reported and no further action taken.  If DFIX finds an unallocated
  15. **    cluster it marks it's local copy of the FAT. At the end of the testing
  16. **    the user is asked if he wishes to permanently mark the cluster as BAD.
  17. **    
  18. */
  19.  
  20. /*
  21. **
  22. **    DFIX is a substitute for the disktest program included with Version 3
  23. **    of The Norton Utilities (tm). The Norton package contains many other
  24. **    useful tools. I wrote this program and am placing it in public domain
  25. **    because of it's (sometimes) critical value.
  26. **
  27. **    This program may be freely copied and used for any non-commercial
  28. **    purpose.
  29. **
  30. **                Howard Rumsey
  31. **                Caltech
  32. **                Pasadena, CA 91125
  33. **
  34. **                CompuServe [72426,3722]
  35. **                December 10, 1986
  36. **
  37. **    v1.2 Toad Hall Tweak, 7 May 91
  38.     Slight touches for Turbo C compile.
  39.     Reformatted to a "normal" indentation, etc., ala K&R.
  40.     No functional changes.
  41. */
  42.  
  43. #include <stdio.h>
  44. #include <ctype.h>
  45.  
  46. #define DOS12 4086        /* FAT 12 or 16 bit MAGIC NUMBER */
  47.  
  48. typedef unsigned int uint;
  49.  
  50. #define BSIZE (14+2*8)    /* Should be the size of the following structure */
  51. struct bootsec {        /* BOOT sector structure */
  52.     char jump[3];        /* jump around this stuff */
  53.     char oem[8];        /* OEM name, version */
  54.     uint bytpsec;        /* bytes per sector */
  55.     char secpclu;        /* sectors per cluster */
  56.     uint fatsec;        /* no. reserved sectors = FAT start */
  57.     char nfats;            /* number of FATs */
  58.     uint ndir;            /* number of ROOT directory entries */
  59.     uint totsec;        /* number of sectors in this partition */
  60.     char meddes;        /* media descriptor byte */
  61.     uint fatcnt;        /* number of sectors in a single FAT */
  62.     uint secptrk;        /* sectors per track */
  63.     uint nheads;        /* number of heads this device */
  64.     uint hidsec;        /* number of hidden sectors */
  65. } *boot;
  66.  
  67. int fat12;            /* TRUE if 12 bit FAT entries */
  68. int badmark;        /* FAT flag used to mark a bad cluster ... */
  69.                     /* 0xff7 for 12 bit FATs, 0xfff7 for 16 bit FATs */
  70. int rdsize;            /* ROOT directory size in sectors */
  71. char *fattab;        /* pointer to local copy of FAT */
  72. char *clubuf;        /* points to cluster input buffer */
  73.  
  74. extern struct {        /* communicate area for device allocation data */
  75.     int d;            /* device number A=0,... */
  76.     char mb;        /* media byte */
  77.     char spc;        /* sectors per cluster */
  78.     uint nc;        /* number clusters */
  79.     uint ss;        /* sector size */
  80. } ALLOCTAB;
  81.  
  82. #ifdef __TURBOC__
  83. #include <stdlib.h>        /* malloc() */
  84. /* prototypes (I like prototypes!) */
  85. void show_usage(void);
  86. void errexit(char *str);
  87. char *plural(int n);
  88. void doOpen(int dev);
  89. void doDisk(int dev);
  90. int fatstat(unsigned c);
  91. void pokefat(unsigned c,unsigned bm);
  92. extern int defaultdev(void);
  93. extern void devAlloc(void);
  94. extern int rdDevice(int dev, int startsec, int nrsecs, char *buffaddr);
  95. extern int wrDevice(int dev, int startsec, int nrsecs, char *buffaddr);
  96.  
  97. #else
  98. char *malloc(), *gets();
  99. #endif
  100.  
  101. main(ac,av) char *av[]; {
  102.     int dev;
  103.  
  104.     printf("DFIX Version 1.2 Copyright (C) 1986 Howard Rumsey Jr.\n\n");
  105. #ifdef __TURBOC__
  106.     if(_osmajor < 2)
  107. #else
  108.     if((dosVersion() & 0xff) < 2)
  109. #endif
  110.         errexit("Must have DOS 2.0 or higher.\n");
  111.  
  112.     if(ac == 1) {
  113.         show_usage();
  114.         dev = defaultdev();
  115.     }
  116.     else {
  117.         if(av[1][1] != ':' || !isalpha(av[1][0])) {
  118.             show_usage();
  119.             exit(1);
  120.         }
  121.         dev = toupper(av[1][0])-'A';
  122.     }
  123.     doOpen(dev);
  124.     doDisk(dev);
  125.     return 0;
  126. }
  127.  
  128. void show_usage(void)
  129. {
  130.     fprintf(stderr, "DFIX will test the whole DOS partition.\n");
  131.     fprintf(stderr, "If you wish, it will mark bad sectors in the FAT.\n");
  132.     fprintf(stderr, "Usage:\n");
  133.     fprintf(stderr, "  dfix [d:]\n");
  134.     fprintf(stderr, "where d: is a device specifier.\n");
  135. }
  136.  
  137. void errexit(str) char *str;
  138. {
  139.     fputs(str, stderr);
  140.     exit(-1);
  141. }
  142.  
  143. char *plural(n) int n;
  144. {
  145.     return n>1 ? (char *)"s" : (char *)"";
  146. }
  147.  
  148. void doOpen(dev) int dev;
  149. {
  150.     /* Check the size of bootsec to avoid a mismatch between
  151.         "C" and DOS data allocation */
  152.     if(sizeof(struct bootsec) != BSIZE)
  153.         errexit("BOOT sector data problem. Sorry!\n");
  154.  
  155.     /* Gather and print the device parameters */
  156.  
  157.     ALLOCTAB.d = dev;
  158.     devAlloc();        /* build the device allocation table */
  159.     boot = (struct bootsec *) malloc(ALLOCTAB.ss);
  160.     if(boot == NULL)
  161.         errexit("Can't allocate BOOT buffer\n");
  162.     if(rdDevice(dev, 0, 1, (char *) boot) != 0)
  163.         errexit("Can't read BOOT sector\n");
  164.  
  165.     /* test for compatibility of BOOT sector and ALLOCTAB */
  166.     if(ALLOCTAB.mb  != boot->meddes ||
  167.        ALLOCTAB.spc != boot->secpclu ||
  168.        ALLOCTAB.ss  != boot->bytpsec )
  169.         errexit("BOOT sector information error. Possibly non-DOS 2+ media.\n");
  170.  
  171.     /* do we have 12 bit FAT entries? */
  172.     fat12 = (ALLOCTAB.nc <= DOS12);
  173.     badmark = fat12 ? 0xff7 : 0xfff7;
  174.     /* compute ROOT directory size */
  175.     rdsize = (int) ((boot->ndir * 32L)/boot->bytpsec);
  176.  
  177.     /* print the device information */
  178.     printf("\nInformation for Device %c:\n",'A'+dev);
  179.     printf("  OEM name: %8s\n",boot->oem);
  180.     printf("  There are %d bytes per sector.\n",boot->bytpsec);
  181.     if(boot->secpclu == 1)
  182.         printf("  There is one sector per cluster.\n");
  183.     else
  184.         printf("  There are %d sectors per cluster.\n",boot->secpclu);
  185.     printf("  There are %d clusters numbered from 2.\n", ALLOCTAB.nc);
  186.     if(boot->nfats == 1)
  187.         printf("  There is one FAT, %d sector%s long.\n",
  188.                 boot->fatcnt, plural(boot->fatcnt));
  189.     else
  190.         printf("  There are %d FATs, each %d sector%s long.\n",
  191.                 boot->nfats, boot->fatcnt, plural(boot->fatcnt));
  192.     printf("  The ROOT directory can hold %d entries and is %d sectors long.\n",
  193.             boot->ndir, rdsize);
  194. }
  195.  
  196.  
  197. void doDisk(dev) int dev;
  198. /* read the FATs, ROOT-dir, and clusters */
  199. {
  200.     int lsec;                    /* logical sector number */
  201.     int jf, kf;
  202.     int nbad, newbad, nbadf;     /* counters for bad clusters */
  203.     char yesno[80];                /* answer 'update' question */
  204.  
  205.     /* get space for one FAT and one cluster */
  206.     fattab = malloc(boot->fatcnt * boot->bytpsec);
  207.     if(fattab == NULL)
  208.         errexit("Unable to allocate memory for a FAT.\n");
  209.     clubuf = malloc(boot->bytpsec * boot->secpclu);
  210.     if(clubuf == NULL)
  211.         errexit("Unable to allocate memory for reading clusters.\n");
  212.  
  213.     printf("Reading the first FAT.\n");
  214.     if(rdDevice(dev, boot->fatsec, boot->fatcnt, fattab) != 0)
  215.         errexit("Can't read first FAT. Device unusable.\n");
  216.  
  217.     /* read the rest, one sector at a time */
  218.     lsec = boot->fatsec + boot->fatcnt;
  219.     for(jf=1; jf<boot->nfats; jf++) {
  220.         printf("Reading the next FAT.\n");
  221.         for(kf=0; kf<boot->fatcnt; kf++) {
  222.             if(rdDevice(dev, lsec++, 1, clubuf) != 0)
  223.                 errexit("Error reading second (or later) FAT.\n");
  224.             /* should compair FATs */
  225.         }
  226.     }
  227.  
  228.     printf("Reading the ROOT directory.\n");
  229.     for(jf=0; jf<rdsize; jf++)
  230.         if(rdDevice(dev, lsec++, 1, clubuf) != 0)
  231.             errexit("Error reading the ROOT directory. Device unusable.\n");
  232.  
  233.     nbad = newbad = nbadf = 0;
  234.     printf("Checking the clusters now.\n");
  235.     printf("Cluster      ");
  236.     for(jf=2; jf<ALLOCTAB.nc+2; jf++) {
  237.         printf("\b\b\b\b\b%5d",jf);
  238.         if(fatstat(jf) == badmark) {
  239.             nbad++;
  240.             printf(" is bad.  Already marked as bad.\n");
  241.             printf("Cluster      ");
  242.         }
  243.         else if(rdDevice(dev, lsec, boot->secpclu, clubuf) != 0) {
  244.             nbad++;
  245.             printf(" is bad.  ");
  246.             if(fatstat(jf)) {
  247.                 nbadf++;
  248.                 printf("\007Included in some file.  Not marked.\n");
  249.             }
  250.             else {
  251.                 newbad++;
  252.                 printf("\007Unallocated.\n");
  253.                 pokefat(jf,badmark);
  254.             }
  255.             printf("Cluster      ");
  256.         }
  257.         lsec += boot->secpclu;
  258.     }
  259.     printf("\b\b\b\b\b\b\b\b\b\b\b\b\b");
  260.     if(nbad == 0) {
  261.         printf("No bad clusters were found.\n");
  262.         return;
  263.     }
  264.     printf("The number of bad clusters found was %d.\n",nbad);
  265.     if(nbadf != 0) {
  266.         if(nbad == 1) printf("Some file has a bad cluster.\n");
  267.         else printf("One or more files have bad clusters.");
  268.         printf("The DOS command:\n  copy *.